#ifndef __USER_CODE_COMPILE_EVENT_HPP__
#define __USER_CODE_COMPILE_EVENT_HPP__


#include "base_event.hpp"


namespace run_code_event_space {

struct user_code_compile_event : base_event<user_code_compile_event>  {
    template <class U>
    ProcessStatus execute_impl(run_code_context_t<U>& context);
};

template <class U>
ProcessStatus user_code_compile_event::execute_impl(run_code_context_t<U>& context) {
    ProcessStatus ps;
    const RuncodeParams& params = context.params;
    const U& judge_type = context.judge_type;
    auto& [userLang, userCodeFile, userBinFile, userCompileStr, userRunStr] = judge_type.userCodeInfo;
    if constexpr (std::is_same_v<U, ModuleJudge>) {
        const auto& spjFiles = judge_type.spjFiles;
        const auto& spjCacheFiles = judge_type.spjCacheFiles;
        auto spjFileIt = std::find_if(spjFiles.begin(), spjFiles.end(), [&](const string& file){
            return endWith(file, "."s + params.language + "." + userLang->suffix);
        });
        if (spjFileIt == spjFiles.end()) {
            spjFileIt = std::find_if(spjFiles.begin(), spjFiles.end(), [&](const string& file) {
                return endWith(file, "."s + userLang->suffix);
            });
        }
        Log::instance().getOutput() << "find correct stdFile :" << *spjFileIt << endl;

        auto index = std::distance(spjFiles.begin(), spjFileIt);
        // 仅检查是否拷贝成功
        ps = general_execution_strategy::_copy<false>(*spjFileIt, spjCacheFiles[index], DEFAULT_LANG);

        if (ps.result != RUN_OK) {
            return ps;
        }
        
        Log::instance().getOutput() << "success copy spjFile form '" << *spjFileIt << "' to '" << spjCacheFiles[index] << "'" << endl;

        if (spjFileIt == spjFiles.end()) {
            return ProcessStatus {
                    .result = LESS_SPJFILE,
                    .error = "less [" + params.language + "] spjFile",
            };
        }

        auto updateFun = [&]() {
            auto spjCode = fileToStr(spjCacheFiles[index]);
            auto userCode = fileToStr(userCodeFile);
            std::ofstream userCodeFs{userCodeFile};
            userCodeFs << spjCode;
            userCodeFs << endl;
            userCodeFs << userCode;

            Log::instance().getOutput() << "userFile append ok" << endl;

            return ProcessStatus{.result = RUN_OK};
        };
        ps = general_execution_strategy::_copy<true>(judge_type.userFile, userCodeFile, userLang, updateFun);
    } else {
        ps = general_execution_strategy::_copy<true>(judge_type.userFile, userCodeFile, userLang);
    }
    if (ps.result != RUN_OK) {
        ps.result = SYS_ERROR;
        Log::instance().getOutput() << "copy error" << endl;
        return ps;
    }
    ps = general_execution_strategy::_compile<true>(userCodeFile, userBinFile, userCompileStr);
    if (ps.result != RUN_OK) {
        ps.result = CE;
        return ps;
    }
    judge_type.userCompileOk = true;
    return ps;
}

}
#endif /* __USER_CODE_COMPILE_EVENT_HPP__ */
